#pragma once
#include <pthread.h>
#include <queue>
#include <iostream>
#include <unordered_map>
#include <string>
#include <unistd.h>
#include <cassert>
#define NUM 5
template <class T>
class Thread;
template <class T>
struct data
{
    data(std::unordered_map<int, IO *> &ptr) : _ptr(ptr)
    {
    }
    std::unordered_map<int, IO *> &_ptr;
    Thread<T> *_str;
    int _sock;
};
template <class T>
class Thread
{
public:
    static Thread<T> *Get()
    {
        return _str;
    }
    void Run(bool &button, std::unordered_map<int, IO *> &ptr, int sock)
    {
        if (button)
        {
            button = false;
            for (size_t i = 0; i < NUM; i++)
            {
                data<T> *p = new data<T>(ptr);
                p->_ptr = ptr;
                p->_str = this;
                p->_sock = sock;
                pthread_create(_tid + i, nullptr, routine, p);
            }
        }
    }
    static void *routine(void *args)
    {
        pthread_detach(pthread_self());
        data<T> *ptr = (data<T> *)(args);
        T task;
        while (true)
        {
            // 获取业务
            ptr->_str->pop(task);
            // 根据协议切割字符串
            Pro analyze(task);
            ptr->_sock = analyze.cut();
            // 反序列化
            Code s;
            for (auto e : analyze._v)
            {
                int n = s.code(e);
                // 构建响应
                std::string respon = std::to_string(n);
                respon += '\n';
                // 返回响应
                auto cur = ptr->_ptr.find(ptr->_sock);
                assert(cur != ptr->_ptr.end());
                cur->second->_outbuffer.clear();
                cur->second->_outbuffer += respon;
                cur->second->esp->Change(ptr->_sock, true);
            }
        }
        delete ptr;
        return nullptr;
    }
    void pop(T &request)
    {
        pthread_mutex_lock(&_mtx);
        while (_q.size() == 0)
        {
            pthread_cond_wait(&_concuser, &_mtx);
        }
        request += _q.front();
        _q.pop();
        std::cout << "我是线程：" << pthread_self() << std::endl;
        pthread_mutex_unlock(&_mtx);
        pthread_cond_signal(&_product);
    }
    void push(const T &request)
    {
        pthread_mutex_lock(&_mtx);
        while (_q.size() == _num)
        {
            pthread_cond_wait(&_product, &_mtx);
        }
        // 因为是string,所以用emplace减少拷贝,以此来提高效率
        _q.emplace(request);
        pthread_mutex_unlock(&_mtx);
        pthread_cond_signal(&_concuser);
    }
    ~Thread()
    {
        pthread_mutex_destroy(&_mtx);
        pthread_cond_destroy(&_concuser);
        pthread_cond_destroy(&_product);
    }

private:
    Thread(size_t num = NUM) : _num(num)
    {
        // 锁和条件变量的初始化
        pthread_mutex_init(&_mtx, nullptr);
        pthread_cond_init(&_concuser, nullptr);
        pthread_cond_init(&_product, nullptr);
    }

private:
    size_t _num;              // 交易场所最多有几个任务
    pthread_t _tid[NUM];      // 线程池线程个数
    pthread_mutex_t _mtx;     // 互斥锁
    pthread_cond_t _concuser; // 条件变量空
    pthread_cond_t _product;  // 条件变量满
    std::queue<T> _q;         // 交易场所
    static Thread<T> *_str;   // 单列模式
};
template <class T>
Thread<T> *Thread<T>::_str = new Thread<T>;